package com.serialcommunication.controller;

import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.bind.DatatypeConverter;

import org.apache.soap.encoding.Hex;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import com.serialcommunication.communication.Reader;
import com.serialcommunication.communication.Writer;
import com.serialcommunication.enums.Sign;
import com.serialcommunication.gui.Application;
import com.serialcommunication.helper.ActionUtil;
import com.serialcommunication.helper.MessageFactory;
import com.serialcommunication.interfaces.IAction;
import com.serialcommunication.interfaces.IBaseComponent;
import com.serialcommunication.interfaces.ITransmitComponent;
import com.serialcommunication.model.DynamicAction;

public class Coordinator {
	
	private static final String portName = "COM20";
	private static final int BAUT_RATE = 115200;

	private static final MessageFactory messageFactory = new MessageFactory();
	
	private static Application appWindow;
	
	private static Reader reader;
	private static Writer writer;
	
	private String modeEngine1;
	private String modeEngine2;
	private String modeEngine3;

	public Coordinator() {
		
	}
	
	/**
	 * called by read only components. no Value is needed.
	 * @param pEngine
	 * @param pActionName
	 */
	public static void newActionTriggered(ITransmitComponent comp) {
		newActionTriggered(comp, Sign.PLUS);
	}
	
//	public static void newActionTriggered(String pEngineNr, String pCommand, String pValue)  {
//		newActionTriggered(pEngineNr, pCommand, pValue, Sign.PLUS);
//	}

	public static void newActionTriggered(ITransmitComponent comp, Sign pSign)  {
		System.out.println(comp.getValue());
		System.out.println(comp.getAction().getCommand());
	
		System.out.println("New Action triggered: " + comp.getAction().getCommand() + " (" + comp.getValue() + ")");
		byte[] message = messageFactory.generateMessage(comp, pSign);
		try{
			writer.write(message);
		} catch (Exception e) {
			// to do
		}
	}
	
	public static void newActionReceived(byte[] buffer) {
		System.out.println("New Action Received");
		
		byte[] byte_1 = new byte [1];
		byte_1[0] = buffer[0];
		Hex byte1AsHex = new Hex(DatatypeConverter.printHexBinary(byte_1));
		System.out.println(byte1AsHex);
		
		byte[] byte_2 = new byte [1];
		byte_2[0] = buffer[1];
		Hex byte2AsHex = new Hex(DatatypeConverter.printHexBinary(byte_2));
		System.out.println(byte2AsHex);
		
		byte[] byte_3 = new byte [1];
		byte_3[0] = buffer[2];
		Hex byte3AsHex = new Hex(DatatypeConverter.printHexBinary(byte_3));
		System.out.println(byte3AsHex);
		
		byte[] byte_4 = new byte [1];
		byte_4[0] = buffer[3];
		Hex byte4AsHex = new Hex(DatatypeConverter.printHexBinary(byte_4));
		System.out.println(byte4AsHex);
		
		byte[] byte_5 = new byte [1];
		byte_5[0] = buffer[4];
		Hex byte5AsHex = new Hex(DatatypeConverter.printHexBinary(byte_5));
		System.out.println(byte5AsHex);
		
		byte[] byte_6 = new byte [1];
		byte_6[0] = buffer[5];
		Hex byte6AsHex = new Hex(DatatypeConverter.printHexBinary(byte_6));
		System.out.println(byte6AsHex);
		
		byte[] byte_7 = new byte [1];
		byte_7[0] = buffer[6];
		Hex byte7AsHex = new Hex(DatatypeConverter.printHexBinary(byte_7));
		System.out.println(byte7AsHex);
		
		byte[] byte_8 = new byte [1];
		byte_8[0] = buffer[7];
		Hex byte8AsHex = new Hex(DatatypeConverter.printHexBinary(byte_8));
		System.out.println(byte8AsHex);
		
		IAction actionReceived = ActionUtil.getActionByCommand(byte3AsHex.toString());
		
		if (actionReceived.getTitle().equals("TEST_LINK_OK")) {
			appWindow.linkOk();
		} 
		
		else if (actionReceived.getTitle().equals("TEST_LINK_NOT_OK")) {
			appWindow.linkNotOk();
		} 
		else {
			byte[] payloadBytes = new byte[3];
			payloadBytes[0] = byte_4[0];
			payloadBytes[1] = byte_5[0];
			payloadBytes[2] = byte_6[0];
			
			String payloadString = DatatypeConverter.printHexBinary(payloadBytes);
			System.out.println("Payload: " + payloadString);
		
			String asHexStr = DatatypeConverter.printHexBinary(buffer);
		    System.out.println(asHexStr);
		    System.out.println(actionReceived.getTitle());
		    appWindow.getComponentByName("1", actionReceived.getTitle()).setValue(new Hex(payloadString).toString());
		}
	}
	
	public static void setApplicationWindow(Application window) {
		appWindow = window;
	}
	
	public static  void setReceivedActionValue(String engine, DynamicAction action, String payload) {
		
	}
	
	public static void modeChanged(String pNewMode, String pEngine ) {
		System.out.println("Mode changed to " + pNewMode + " for engine " + pEngine);
	}
	
	public static void initCommunication() {
		CommPort commPort = null;
		InputStream dataInputStream = null;
		OutputStream dataOutputStream = null;
		try {
			CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
			if (portIdentifier.isCurrentlyOwned()) {
				System.out.println("Error: Port is currently in use");
			} else {
				commPort = portIdentifier.open("Test", 2000);
				if (commPort instanceof SerialPort) {
					SerialPort serialPort = (SerialPort) commPort;
					serialPort.setSerialPortParams(BAUT_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
							SerialPort.PARITY_NONE);

					dataInputStream = serialPort.getInputStream();
					dataOutputStream = serialPort.getOutputStream();
				} else {
					System.out.println("Error: Only serial ports are handled by this example.");
				}
			}
		}
		catch (Exception e) {
			
		}
		try {
			writer = new Writer(dataOutputStream);
			reader = new Reader(dataInputStream);
			Thread t1 = new Thread( new Reader(dataInputStream) );
			t1.start();
		}
		catch (Exception e) {
			
		}
	}
	
	public String getModeEngine1() {
		return modeEngine1;
	}

	public void setModeEngine1(String modeEngine1) {
		this.modeEngine1 = modeEngine1;
	}

	public String getModeEngine2() {
		return modeEngine2;
	}

	public void setModeEngine2(String modeEngine2) {
		this.modeEngine2 = modeEngine2;
	}

	public String getModeEngine3() {
		return modeEngine3;
	}

	public void setModeEngine3(String modeEngine3) {
		this.modeEngine3 = modeEngine3;
	}
}
